﻿using EBA.IoC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;


namespace EBA.Data
{
    /// <summary>
    /// 主键值修改上下文
    /// </summary>
    public class EntityKeyChangeContext
    {
        static IContainer _Container;
        /// <summary>
        /// 默认<see cref="IContainer"/>
        /// </summary>
        public static IContainer Container
        {
            get
            {
                if (_Container == null)
                {
                    _Container = new ContainerConfiguration()
                    .CreateContainer();
                }

                return _Container;
            }
            set
            {
                _Container = value;
            }
        }


        Dictionary<Type, IEntityKeyChangeTracker> EntityKeyChangeTrackers { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public EntityKeyChangeContext()
        {
            this.EntityKeyChangeTrackers = new Dictionary<Type, IEntityKeyChangeTracker>();
        }

        EntityKeyChangeTracker<TEntity> GetChangeTracker<TEntity>()
        {
            var entityType = typeof(TEntity);
            EntityKeyChangeTracker<TEntity> changeTracker;
            if (this.EntityKeyChangeTrackers.ContainsKey(entityType))
            {
                changeTracker = (EntityKeyChangeTracker<TEntity>)this.EntityKeyChangeTrackers[entityType];
            }
            else
            {

                changeTracker = new EntityKeyChangeTracker<TEntity>();

                var monitors = EntityKeyChangeContext.Container.GetExports<IEntityKeyMonitor>();

                foreach (var monitor in monitors)
                {
                    monitor.AddEventListeners<TEntity>(changeTracker);
                }

                this.EntityKeyChangeTrackers.Add(entityType, changeTracker);
            }

            return changeTracker;
        }

        /// <summary>
        /// 删除主键
        /// </summary>
        /// <param name="context">事务上下文</param>
        /// <param name="key">主键值</param>
        public void DeleteKey<TEntity>(IUnitOfWork context, object key)
        {
            var changeTracer = this.GetChangeTracker<TEntity>();

            changeTracer.OnEntityKeyDeleting(context, key);
        }

        /// <summary>
        /// 删除主键值
        /// </summary>
        /// <param name="context">事务上下文</param>
        /// <param name="query">对象查询器</param>
        /// <param name="filter">主键值查询条件</param>
        public void DeleteKeys<TEntity>(IUnitOfWork context, IQuery<TEntity> query, Expression<Func<TEntity, bool>> filter)
        {
            var changeTracer = this.GetChangeTracker<TEntity>();

            changeTracer.OnEntityKeysDeleting(context, query, filter);
        }

        /// <summary>
        /// 修改主键值
        /// </summary>
        /// <param name="context">事务上下文</param>
        /// <param name="query">对象查询器</param>
        /// <param name="originalKey">旧主键值</param>
        /// <param name="currentKey">新主键值</param>
        public void ChangeKey<TEntity>(IUnitOfWork context, IQuery<TEntity> query,object originalKey, object currentKey)
        {
            var changeTracer = this.GetChangeTracker<TEntity>();

            changeTracer.OnEntityKeyChanging(context,query, originalKey, currentKey);
        }

    }
}
